feat(calm-widgets): extend render-interfaces to support related mode#2701
Conversation
…rchitecture widget When focus-interfaces is used with edges=connected, all interfaces on all visible nodes are rendered, including unrelated ones on connected nodes. The new ignore-connected-interfaces option restricts rendering to only the interfaces that appear in the active (filtered) relationships, hiding all others regardless of which node they belong to. Closes finos#1600
1b8d5a8 to
4815c7f
Compare
There was a problem hiding this comment.
Pull request overview
Adds a new ignore-connected-interfaces option to the block-architecture widget (calm-widgets) to declutter focused interface views by rendering only interfaces that participate in the currently active/filtered relationships.
Changes:
- Introduces the
ignore-connected-interfacesoption (types + parsing) and threads anactiveInterfaceIdsallowlist into VM construction. - Updates node/container VM factories to optionally filter rendered interfaces, with unit coverage for the new filtering behavior.
- Adds an end-to-end fixture demonstrating before/after output and documents the new option in
calm-widgets/README.md.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| calm-widgets/test-fixtures/block-architecture-widget/ignore-connected-interfaces/template.hbs | New fixture template showing before/after usage of the option. |
| calm-widgets/test-fixtures/block-architecture-widget/ignore-connected-interfaces/expected.md | Expected Mermaid output for the new fixture (before/after). |
| calm-widgets/test-fixtures/block-architecture-widget/ignore-connected-interfaces/context.json | Fixture model containing interfaces + relationships to exercise filtering. |
| calm-widgets/src/widgets/block-architecture/types.ts | Adds the new option to public and normalized options types. |
| calm-widgets/src/widgets/block-architecture/core/vm-builder.ts | Computes and passes “active interfaces” allowlist into container/node building. |
| calm-widgets/src/widgets/block-architecture/core/visibility-resolver.ts | Extends VisibilityResult to expose seedNodes from strategies. |
| calm-widgets/src/widgets/block-architecture/core/options-parser.ts | Parses ignore-connected-interfaces into normalized options. |
| calm-widgets/src/widgets/block-architecture/core/options-parser.spec.ts | Unit tests for parsing the new option. |
| calm-widgets/src/widgets/block-architecture/core/factories/vm-factory-interfaces.ts | Extends VMNodeFactory.createLeafNode signature to accept activeInterfaceIds. |
| calm-widgets/src/widgets/block-architecture/core/factories/node-factory.ts | Filters rendered interfaces using the passed allowlist. |
| calm-widgets/src/widgets/block-architecture/core/factories/node-factory.spec.ts | Unit tests for interface filtering behavior (including empty allowlist). |
| calm-widgets/src/widgets/block-architecture/core/builders/container-builder.ts | Threads activeInterfaceIds through to the node factory. |
| calm-widgets/src/widgets/block-architecture/core/builders/container-builder.spec.ts | Verifies activeInterfaceIds are passed to the node factory. |
| calm-widgets/src/widgets.e2e.spec.ts | Adds an E2E test that runs the new fixture. |
| calm-widgets/README.md | Documents the new widget option and links the new fixture example. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
rocketstack-matt
left a comment
There was a problem hiding this comment.
Clean implementation that addresses #1600. The new collectActiveInterfaceIds matches the widget's established toKindView(...).kind === 'connects' idiom, and the unit tests plus the before/after e2e fixture genuinely exercise the behaviour (7 interfaces -> 3 active).
Two points inline: one dead seedNodes field worth removing before merge, and a non-blocking naming question.
For the record, Copilot's global-uniqueness concern is incorrect - idsAreUnique (shared spectral rule) enforces interface-id uniqueness across the whole architecture, so the Set<string> allowlist is safe; you already replied to that effect.
| | `render-node-type-shapes` | boolean | `false` | If `true`, render nodes with different Mermaid shapes based on their `node-type`. Supports built-in CALM types: `actor`, `database`, `webclient`, `service`, `system`, `messagebus`. | | ||
| | `node-type-map` | stringified JSON map | — | Custom mapping of node types to built-in shapes, e.g. `{"cache": "database", "queue": "messagebus"}`. Only used when `render-node-type-shapes` is `true`. | | ||
| | `render-interfaces` | boolean | `false` | If `true`, render each node’s `interfaces` as small interface boxes connected by dotted lines. | | ||
| | `ignore-connected-interfaces` | boolean | `false` | Only meaningful when `render-interfaces=true`. If `true`, only render interfaces that appear in the active (filtered) relationships — hiding all others. Useful with `focus-interfaces` + `edges=connected` to declutter connected nodes while keeping the relevant interface endpoints visible. | |
There was a problem hiding this comment.
The name vs behaviour is slightly off: ignore-connected-interfaces also drops inactive interfaces on the focused/seed node - e.g. audit-log-iface on payment-service in the fixture - not just connected nodes. The description here is accurate ("hiding all others"), but the option name implies only connected-node interfaces are affected. Consider a clearer name (only-active-interfaces / ignore-inactive-interfaces) or a one-line note that seed-node interfaces are filtered too. (non-blocking)
There was a problem hiding this comment.
It bugged me too. I'll decide on an alternative.
There was a problem hiding this comment.
Decided to extend render-interfaces from a boolean to a three-value enum: false | true | 'related'. The related mode renders only interfaces that appear in the active filtered relationships, hiding all others (including unrelated interfaces on seed nodes).
This avoids adding a separate flag entirely — one option, three modes — and sidesteps the naming debate. render-interfaces=related reads naturally as a specialisation of render-interfaces=true.
There was a problem hiding this comment.
I went through many options, with only- prefixes, ignore- prefixes or include- prefixes.
just extending render-interfaces to be a three-value enum retains backwards compatibility but gives flexibility in the same place on how many interfaces are shown - none, all, or some.
seedNodes was added to VisibilityResult and passed through from the strategy chain, but no downstream consumer (vm-builder) ever reads it.
…er-interfaces=related Rather than a separate boolean flag, extend the existing render-interfaces option to a three-value enum: false | true | 'related'. The 'related' mode renders only interfaces that appear in the active filtered relationships, hiding all others. This is a cleaner API surface — one option, three modes — and avoids the naming ambiguity of the previous flag.
…b.com/markscott-ms/architecture-as-code into feat/1600-ignore-connected-interfaces
|
The description of this PR has been updated following @rocketstack-matt comment #2701 (comment) |
Description
Closes #1600
Extends the
render-interfacesoption on theblock-architecturewidget to a three-value enum:false | true | 'related'.When using
focus-interfaceswithedges=connectedandrender-interfaces=true, the widget currently renders all interfaces on every visible node — including unrelated ones on connected nodes. This makes the diagram cluttered and harder to read when the user is trying to understand a specific interface and its connections.With
render-interfaces=related, only the interfaces that actually participate in the active relationships are rendered. All other interfaces (on seed nodes and connected nodes alike) are hidden. Edges still route to the interface sub-nodes, which are now correctly rendered.Option values
false(default)truerelatedExample (payment architecture)
Focusing on
payment-apiwithedges=connected render-interfaces=true:render-interfaces=truerender-interfaces=relatedpayment-api(seed)fraud-check-api(active destination)email-iface(active destination)audit-log-iface(seed, not in any active rel)risk-model-iface,score-db-iface(connected, inactive)sms-iface(connected, inactive)Screenshots
render-interfaces=true(existing behaviour){{block-architecture focus-interfaces="payment-api" render-interfaces=true edges="connected"}}render-interfaces=related(new behaviour){{block-architecture focus-interfaces="payment-api" render-interfaces="related" edges="connected"}}Type of Change
Affected Components
cli/)calm/)calm-ai/)calm-hub/)calm-hub-ui/)calm-server/)calm-widgets/)docs/)shared/)calm-plugins/vscode/)Commit Message Format ✅
feat(calm-widgets): extend render-interfaces to support related modeTesting
New tests added:
node-factory.spec.ts: filters interfaces byactiveInterfaceIds; produces no interfaces when set is emptycontainer-builder.spec.ts: passesactiveInterfaceIdsthrough to the node factoryoptions-parser.spec.ts: parsesrender-interfaces=relatedrender-interfaces-related/: side-by-side before/after using a 3-node payment architectureChecklist